<?php
namespace App\Components;

use App\Components\Redis;
use Exception;
use Monolog\Registry as Monolog;

class EventService
{
    public static function getEventQueueName(): string
    {
        $queueName = strtoupper($_ENV['app_name']) . ':';
        $queueName .= 'EVENT:QUEUE';
        return $queueName;
    }

    /**
     * 分发事件
     * @param string $event 事件名称
     * @param mixed $payload 事件消息体
     * @param array $option delay=延迟发送秒数, live=消息生存秒数
     * @return bool 是否发送成功
     */
    public static function dispatch(string $event, $payload = [], array $option = []): bool
    {
        $eventProvider = require ROOT_PATH . 'bootstrap/event.php';
        if (!isset($eventProvider[$event])) {
            Monolog::getInstance('app')->notice('分发事件,事件名称未定义', [
                'event' => $event,
                'payload' => $payload,
                'provider' => $eventProvider,
            ]);
            return false;
        }
        if (isset($option['delay'])) {
            $option['delay'] *= 1000;
            if ($option['delay'] <= 0) {
                return false;
            }
        }
        if (isset($option['live'])) {
            if ($option['live'] <= 0) {
                return false;
            }
        }

        $msg = [
            'event' => $event,
            'payload' => serialize($payload),
            'created_at' => date('Y-m-d H:i:s'),
        ];

        try {
            $context = Redis::queueContext();
            $queue = $context->createQueue(self::getEventQueueName());
            $message = $context->createMessage(json_encode($msg));
            $context = $context->createProducer();
            if (isset($option['delay'])) {
                $context = $context->setDeliveryDelay($option['delay']);
            }
            if (isset($option['live'])) {
                $context = $context->setTimeToLive($option['live']);
            }
            $context->send($queue, $message);
        } catch (Exception $e) {
            Monolog::getInstance('app')->error('分发事件,消息发送错误', [
                'event' => $event,
                'payload' => $payload,
                'error' => $e->getMessage(),
            ]);
            return false;
        }
        return true;
    }
}
